<?php
namespace Base\Controller;

use Zend\View\Exception\RuntimeException;

use Doctrine\ORM\EntityManager;

use Zend\Mvc\Controller\AbstractActionController,
    Zend\View\Model\ViewModel;
use Zend\Form\Form;


abstract class AbstractCrudController extends AbstractActionController {
	
	protected $em;
	protected $service;
	protected $entity;
	protected $form;
	protected $route;
	protected $controller;
	protected $namespace;
	protected $pasteView;
	
	
	/**
	 * @method indexAction()
	 * Responsável por fazer listagem de dados.
	 * @see \Zend\Mvc\Controller\AbstractActionController::indexAction()
	 * @access public
	 */
	public function indexAction() {
		
		try {
			
			$list = $this->getEntityManager()
			             ->getRepository( $this->entity )
			             ->findAll();
			
			
			$messages = $this->flashMessenger()
			 				 ->setNamespace($this->namespace)
			 				 ->getMessages();
			
			try {
				
				return new ViewModel(array(
						               'data' => $list,
						               'messages' => $messages
						             )
						    );
			} catch ( RuntimeException $r ) {
				
				$this->flashMessenger()
					 ->setNamespace( $this->namespace )
					 ->addMessage( array(
							'error' => $r->getMessage(),
							'info'  => $r->getTraceAsString()
					 ) );
					 
				return $this->redirect()->toRoute(
										 		$this->route,
										 		array( 'controller' => $this->controller
				 		                  ) );
			}
		
		} catch( \Exception $e ) {
				
		       $this->flashMessenger()
					->setNamespace( $this->namespace )
					->addMessage( array(
							'error' => $e->getMessage(),
							'info' => $e->getTraceAsString()
					) );
					
			   return $this->redirect()->toRoute(
												$this->route,
												array( 'controller' => $this->controller
										 ) );
		}
		
	}
	
	
	
	/**
	 * @method newAction()
	 * Criar um novo registro
	 * @return \Zend\View\Model\ViewModel
	 * @access public
	 */
	public function newAction() {
		
		try {
			
			$form = new $this->form();
			$request = $this->getRequest();
			
			if ( $request->isPost() ) {
				
				$form->setData($request->getPost());
				
				if ( $form->isValid() ) {
				
					$service = $this->getServiceLocator()->get( $this->service );
					
					if ( $service->save( $request->getPost()->toArray() ) ) {
					
						$fm = $this->flashMessenger()
								   ->setNamespace( $this->namespace )
								   ->addMessage( array('success' => 'Dados armazenados com sucesso') );
						
						return $this->redirect()->toRoute( 
														$this->route, 
														array( 'controller' => $this->controller 
									              ) );
					}
				}
			}

			try {
				
			   return $this->renderView(array('form'=>$form));
			   
			} catch ( RuntimeException $r ) {
			
				$this->flashMessenger()
					 ->setNamespace( $this->namespace )
					 ->addMessage( array(
							'error' => $r->getMessage(),
							'info'  => $r->getTraceAsString()
				) );
					 
				return $this->redirect()->toRoute(
									 		$this->route,
									 		array( 'controller' => $this->controller
				 		                  ) );
			}
		
		} catch( \Exception $e ) {
				
			$fm = $this->flashMessenger()
					   ->setNamespace( $this->namespace )
					   ->addMessage( array(
								'error' => $e->getMessage(),
								'info' => $e->getTraceAsString()
					   ) );
					   
	        return $this->redirect()->toRoute(
	   								$this->route,
	   								array( 'controller' => $this->controller
	   							  ) );
		}
		
		
		
		
	}
	
	
	
	
	/**
	 * @method viewAction()
	 * Visualiza um registro
	 * @return \Zend\View\Model\ViewModel
	 * @access public
	 */
	public function viewAction() {
	
		try {
			
			$id = $this->params()->fromRoute('id',0);
			$form = new $this->form();
			
			$this->disableFormFields( $form );
		
			if($id) {
								
				$entity = $this->getEntityManager()->getReference($this->entity, $id);

                if ( $entity )
                    $form->setData( $entity->toArray() );
				
				try {						
				
					return $this->renderView( array(
							'form' => $form
					) );
				
				} catch ( RuntimeException $r ) {
				
					$this->flashMessenger()
						 ->setNamespace( $this->namespace )
						 ->addMessage( array(
								'error' => $r->getMessage(),
								'info'  => $r->getTraceAsString()
					) );
						 
				    return $this->redirect()->toRoute(
											 		$this->route,
											 		array( 'controller' => $this->controller
				 		                      ) );
				}		
			}
		
		} catch( \Exception $e ) {
		
			$fm = $this->flashMessenger()
					   ->setNamespace( $this->namespace )
					   ->addMessage( array(
								'error' => $e->getMessage(),
								'info' => $e->getTraceAsString()
					   ) );
					   
		    return $this->redirect()->toRoute(
									   		$this->route,
									   		array( 'controller' => $this->controller
		   		                       ) );
		}
	}
	
	
	
	/**
	 * @method editAction()
	 * Editar um registro
	 * @return \Zend\View\Model\ViewModel
	 * @access public
	 */
	public function editAction() {
		
		try {
		
			$form = new $this->form();
			$request = $this->getRequest();
			
			$repository = $this->getEntityManager()
			                   ->getRepository( $this->entity );
			
			$id = $this->params()->fromRoute('id', 0);
			
			$entity = $repository->find( $id );
			
			if ( $entity )
				$form->setData( $entity->toArray() );
			
			
			if ( $request->isPost() ) {
					
				$form->setData($request->getPost());
					
				if ( $form->isValid() ) {
					
					$service = $this->getServiceLocator()->get( $this->service );
					
					if ( $service->save( $request->getPost()->toArray() ) ) {
						
						$fm = $this->flashMessenger()
								   ->setNamespace( $this->namespace )
								   ->addMessage( array('success' => 'Registro alterado com sucesso') );
						
						return $this->redirect()->toRoute(
									$this->route,
									array( 'controller' => $this->controller
								));
					}
				}
			}
		
			try {
			
				return $this->renderView(array(
						                   'form' => $form, 
						                   'id' => $id
						                 ));
			
			} catch ( RuntimeException $r ) {
			
				$this->flashMessenger()
					 ->setNamespace( $this->namespace )
					 ->addMessage( array(
							'error' => $r->getMessage(),
							'info'  => $r->getTraceAsString()
					 ) );
					 
				return $this->redirect()->toRoute(
										 		$this->route,
										 		array( 'controller' => $this->controller
				 		                  ) );
			}
		
		} catch( \Exception $e ) {
			
			$fm = $this->flashMessenger()
					   ->setNamespace( $this->namespace )
					   ->addMessage( array(
					   		             'error' => $e->getMessage(),
					   		             'info' => $e->getTraceAsString()
					   		         ) );
					   
		    return $this->redirect()->toRoute(
									   		$this->route,
									   		array( 'controller' => $this->controller
		   		                      ) );
		}
		
	}
	
	
	
	
	/**
	 * @method deleteAction()
	 * Deleta o registro
	 * @return \Zend\View\Model\ViewModel
	 * @access public
	 */
	public function deleteAction() {

		try {
			
			$params = $this->params()->fromRoute('id');

			if ( isset ( $params ) ) 
			    $ids = explode('-', $params);
			
			if ( is_array( $ids ) ) { 
				
				$service = $this->getServiceLocator()->get( $this->service );
				
				$successMessages = array();
				$errorMessages = array();
				
				foreach ( $ids as $id ) {
					
					$result = $service->remove( $id );	
									
					if ( $result == $id ) {
						
						$successMessages[] = 'Registro ' . $result . ' excluído com sucesso!';
						
					} else {
						
						$errorMessages[] = 'Erro ao tentar excluir o registro ' . $id .'!';
					}
				}
				
				$this->flashMessenger()
					 ->setNamespace( $this->namespace )
					 ->addMessage( array(
								'success' => $successMessages,
								'error'   => $errorMessages
					 )
				);
				
				return $this->redirect()->toRoute(
												$this->route,
												array( 'controller' => $this->controller
						                ) );
				
			} else  
			     throw new \Exception("Parâmetros não encontrados");
		
		} catch( \Exception $e ) {
				
			$fm = $this->flashMessenger()
					   ->setNamespace( $this->namespace )
					   ->addMessage( array(
								'error' => $e->getMessage(),
								'info' => $e->getTraceAsString()
					   ) );
					   
					   
		    return $this->redirect()->toRoute(
									   		$this->route,
									   		array( 'controller' => $this->controller
		   		  					  ) );
		}
	}
	
	
	
	/**
	 * Seta o script.phtml que está em outro lugar.
	 * @return ViewModel
	 * @access protected
	 */
	protected function renderView( Array $vars, $disableLayout = null ) {
	
		$view = new ViewModel();
	
		$rotulos = array('new' =>'Novo Registro',
				         'edit'=>'Editar Registro');
	
		$actionName = $this->getEvent()->getRouteMatch()->getParam('action', 'NA');
		$view->setTemplate( $this->pasteView . '/' . $this->controller . '/crud' );
		
		if($disableLayout) // desabilita o layout
			$view->setTerminal( true );
	
		$vars['action']	 = $actionName;
		$vars['rotuloAction']	= $rotulos[$actionName];
	
		return $view->setVariables($vars);
	
	}
	
	
	
	/**
	 * Seta os campos do formulário como desabilitado
	 * @param Form $form
	 * @access protected
	 */
	protected function disableFormFields( Form $form ) {
		
		$elements = $form->getElements();
			
		foreach ( $elements as $element ) {

			$element->setAttributes(array ( 'readonly' => true, 'disabled' => true ) );
		}
	}
	
	
	
	/**
	 *
	 * @return EntityManager
	 * @access protected
	 */
	protected function getEntityManager() {
	
		if ( null === $this->em ) {
			/**
			 * @var EntityManager
			 */
			$this->em = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
		}
	
		return $this->em;
	}
	
}
